package client;

import java.nio.FloatBuffer;
import java.util.Vector;

import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL13;
import org.lwjgl.opengl.GL20;
import org.lwjgl.util.vector.Matrix4f;
import org.lwjgl.util.vector.Vector2f;

import shared.Tools;
import shared.Vec2f;
import shared.Vec2i;

public class Main_Render {
	ChunkRender [][] m_chunks;
	Actor_Render m_actor_render;
//	Quad m_quad;
//	int m_vshader,m_fshader,m_pshader,m_tintvar,m_viewvar,m_objvar;
	Matrix4f m_viewmatrix;
	FloatBuffer matrix44Buffer;
	int m_textureIds[];
	Main_Sim m_sim;	
	int [] m_variables;
	
	public Main_Render(int [] variables, Main_Sim sim)
	{
		m_sim=sim;
		m_actor_render=new Actor_Render(m_sim.m_actors);
		m_variables=variables;
		m_textureIds=new int[4];
		GL11.glClearColor(0.0f, 0.0f, 0.5f, 0f);

		m_chunks=new ChunkRender[3][];
		for (int i=0;i<3;i++)
		{
			m_chunks[i]=new ChunkRender[3];
		}
		

		LoadTextures();

		m_variables=variables;
		
		m_viewmatrix=new Matrix4f();
		m_viewmatrix.m00=0.08F;
		m_viewmatrix.m11=0.1F;
		m_viewmatrix.m22=1.0F;
		m_viewmatrix.m33=1.0F;
		matrix44Buffer=BufferUtils.createFloatBuffer(16);			
		
	}
	
	public void LoadTextures()
	{
		m_textureIds[0]=Tools.loadPNGTexture("assets/art/tileset0.png", GL13.GL_TEXTURE0);
		m_textureIds[1]=Tools.loadPNGTexture("assets/art/button.png", GL13.GL_TEXTURE0);
		m_textureIds[2]=Tools.loadPNGTexture("assets/art/window.png", GL13.GL_TEXTURE0);
		m_textureIds[3]=Tools.loadPNGTexture("assets/art/widgets0.png", GL13.GL_TEXTURE0);
	}
	

	public void Draw() {
		
		GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);

		//GL20.glUseProgram(m_pshader);
		GL13.glActiveTexture(GL13.GL_TEXTURE0);
		GL11.glBindTexture(GL11.GL_TEXTURE_2D, m_textureIds[0]);
		
		//set tint to default
		GL20.glUniform4f(m_variables[0],1.0F,1.0F,1.0F, 1);
		
		//set standard viewing matrix
		m_viewmatrix.store(matrix44Buffer); matrix44Buffer.flip();
		GL20.glUniformMatrix4(m_variables[1], false, matrix44Buffer);
		
		for (int i=0;i<3;i++)
		{
			for (int j=0;j<3;j++)
			{
				if (m_chunks[i][j]!=null)
				{
					m_chunks[i][j].Draw(matrix44Buffer, m_variables[2], m_variables[0]);
				}
			}
		}		
		GL11.glBindTexture(GL11.GL_TEXTURE_2D, m_textureIds[3]);
		
		for (int i=0;i<3;i++)
		{
			for (int j=0;j<3;j++)
			{
				if (m_chunks[i][j]!=null)
				{
					m_chunks[i][j].Draw2ndPass(matrix44Buffer, m_variables[2], m_variables[0]);
				}						
			}
		}
		
		m_actor_render.Draw(matrix44Buffer, m_variables[2], m_variables[0]);
	}	
	
	public void MoveView(Vec2f p)
	{
		m_viewmatrix.translate(new Vector2f(p.x*-1,p.y*-1));
	}
	
	public void RelocateView(Vec2f p)
	{
		m_viewmatrix.m30=0; m_viewmatrix.m31=0;
		m_viewmatrix.translate(new Vector2f(p.x*-1,p.y*-1));
	}	
	
	public void Generate()
	{
		//attempt to build layers for all visible chunks
		
		//first, figure out world coord, its probably the view matrix m0 and m1 values
		int x=(int)m_viewmatrix.m30/16; int y=(int)m_viewmatrix.m31/16;
		//then make the attempt, we're not guaranteed to have chunks, even with layers
		Vector <Vec2i> test=new Vector <Vec2i>();
		for (int i=0;i<3;i++)
		{
			for (int j=0;j<3;j++)
			{
				if (m_sim.m_chunks[3+i][3+j]!=null)
				{
					test.add(m_sim.m_chunks[3+i][3+j].m_position);
					if (m_chunks[i][j]!=null)
					{
						m_chunks[i][j].Discard();
					}
					m_chunks[i][j]=new ChunkRender(m_sim.m_chunks[3+i][3+j]);
					m_chunks[i][j].Generate(m_sim.m_player.m_layer);	
				}
			}
		}
		for (int i=0;i<test.size();i++)
		{
			for (int j=0;j<test.size();j++)
			{
				
				if (test.get(i).x==test.get(j).x && i!=j && test.get(i).y==test.get(j).y)
				{
					char oshit='f';
					oshit++;
					
				}
			}
		}
	}
	
	public void End()
	{
		//delete texture
		GL11.glDeleteTextures(m_textureIds[0]);
		GL11.glDeleteTextures(m_textureIds[1]);
		GL11.glDeleteTextures(m_textureIds[2]);	
		
		//destroy the chunk render system
		for (int i=0;i<3;i++)
		{
			for (int j=0;j<3;j++)
			{
				if (m_chunks[i][j]!=null)
				{
					m_chunks[i][j].Discard();
				}
			}
		}
		m_actor_render.Discard();
	}
		
}
